package org.jeese.demo;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.StringUtils;
import org.springframework.util.SystemPropertyUtils;

public class ClassScaner implements ResourceLoaderAware {

	private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
	private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(
			this.resourcePatternResolver);

	public static Set<Class<?>> scan(String[] basePackages) {
		ClassScaner cs = new ClassScaner();
		Set<Class<?>> classes = new HashSet<Class<?>>();
		for (String s : basePackages)
			classes.addAll(cs.doScan(s));
		return classes;
	}

	public static Set<Class<?>> scan(String basePackages) {
		return ClassScaner.scan(StringUtils.tokenizeToStringArray(basePackages, ",; \t\n"));
	}

	public final ResourceLoader getResourceLoader() {
		return this.resourcePatternResolver;
	}

	public void setResourceLoader(ResourceLoader resourceLoader) {
		this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
		this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
	}

	public Set<Class<?>> doScan(String basePackage) {
		Set<Class<?>> classes = new HashSet<Class<?>>();
		try {
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
					+ org.springframework.util.ClassUtils.convertClassNameToResourcePath(
							SystemPropertyUtils.resolvePlaceholders(basePackage))
					+ "/**/*.class";
			Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);

			for (int i = 0; i < resources.length; i++) {
				Resource resource = resources[i];
				if (resource.isReadable()) {
					MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
					try {
						classes.add(Class.forName(metadataReader.getClassMetadata().getClassName()));
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
					}
				}
			}
		} catch (IOException ex) {
			throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
		}
		return classes;
	}

	public static void main(String[] args) {
		try {
			Set<Class<?>> set = ClassScaner.scan("org.jeese.demo");
			for (Class<?> clz : set) {
				if (clz.isEnum()) {
					System.out.println(clz.getName());
					// 2.得到所有枚举常量
					Object[] objects = clz.getEnumConstants();
					Method getCode = clz.getMethod("getDescribe");
					Method getName = clz.getMethod("getValue");
					Field[] fields = clz.getFields();
			        for( Field field : fields ){
			            System.out.println( field.getName() + " " +field.get(clz));
			        }
			        Field field = clz.getField("MAP");
			        Map<String, String> map = (Map<String, String>) field.get(clz);
			        System.out.println(map);
//					for (Object obj : objects) {
//						// 3.调用对应方法，得到枚举常量中字段的值
//						System.out.println("code=" + getCode.invoke(obj) + "; name=" + getName.invoke(obj));
//					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}